package com.sy.simpleegg.platform.ychsdk.manager

import android.net.wifi.WifiManager
import android.text.TextUtils
import android.util.ArrayMap
import cn.ych.network.errorhandler.ExceptionHandle
import cn.ych.network.errorhandler.ExceptionHandle.ResponeThrowable
import cn.ych.network.observer.BaseResultObserver
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.aliyun.alink.linkkit.api.ILinkKitConnectListener
import com.aliyun.alink.linksdk.tools.AError
import com.blankj.utilcode.constant.TimeConstants
import com.blankj.utilcode.util.DeviceUtils
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.SDCardUtils
import com.blankj.utilcode.util.ThreadUtils
import com.blankj.utilcode.util.ThreadUtils.SimpleTask
import com.blankj.utilcode.util.TimeUtils
import com.sy.simpleegg.ext.logFile
import com.sy.simpleegg.platform.ychsdk.constant.Constant
import com.sy.simpleegg.util.GsonUtil
import com.ych.ytdevicesdk.IDeviceManager
import com.ych.ytdevicesdk.IDeviceManager.IConnectTestResponse
import com.ych.ytdevicesdk.IDeviceManager.IMqMessageListener
import com.ych.ytdevicesdk.api.BaseResult
import com.ych.ytdevicesdk.api.DeviceConnectLoader
import com.ych.ytdevicesdk.config.App
import com.ych.ytdevicesdk.config.Constants
import com.ych.ytdevicesdk.entity.AliDataEntity
import com.ych.ytdevicesdk.entity.AppInfoEntity
import com.ych.ytdevicesdk.entity.ConnectTestEntity
import com.ych.ytdevicesdk.entity.DeviceStatusBean
import com.ych.ytdevicesdk.entity.DeviceUpdateEntity
import com.ych.ytdevicesdk.entity.DeviceUpdateEntity.UpdatesDTO
import com.ych.ytdevicesdk.entity.HeartbeatEntity
import com.ych.ytdevicesdk.entity.MqCoinEntity
import com.ych.ytdevicesdk.entity.MqDeviceSetRequestData
import com.ych.ytdevicesdk.entity.RegisterEntity
import com.ych.ytdevicesdk.entity.RemoteDeviceConfigEntity
import com.ych.ytdevicesdk.entity.SubRegisterEntity
import com.ych.ytdevicesdk.utils.AliMessageEntity
import com.ych.ytdevicesdk.utils.AliMessageQueueUtils
import com.ych.ytdevicesdk.utils.FileUtils
import com.ych.ytdevicesdk.utils.LogUtilsX
import com.ych.ytdevicesdk.utils.SignatureUtils
import io.reactivex.Observer
import java.text.SimpleDateFormat
import java.util.Date
import java.util.TreeMap
import java.util.concurrent.TimeUnit
import kotlin.concurrent.Volatile

class YchDeviceManager : IDeviceManager {
    private val deviceConnectLoader = DeviceConnectLoader()
    private var aliMessageQueueUtils: AliMessageQueueUtils? = null
    private var isOpenLog = false
    private var isDebug = false
    private var useTestUrl = false
    private var agreement = 1
    private var agreementVer = "0"
    private val cmdBufferStack: ArrayMap<String?, Int?> = ArrayMap<String?, Int?>()
    private val mQCoinBufferStack: ArrayMap<String?, MqCoinEntity?> =
        ArrayMap<String?, MqCoinEntity?>()
    private var mQResponseTimes = 0
    private var productFlag = "00010001"

    @Volatile
    private var initListener: IDeviceManager.InitListener? = null
    private var eventListener: IMqMessageListener? = null
    private var data: RemoteDeviceConfigEntity? = null
    private var getDeviceConfigCount = 0
    private var mAliMqRetryCount = 0

    companion object {
        private var instance: YchDeviceManager? = null
            get() {
                if (field == null) {
                    field = YchDeviceManager()
                }
                return field
            }

        @Synchronized
        fun get(): YchDeviceManager {
            return instance!!
        }
    }

    override fun getDeviceNumber(): String? {
        return Constants.DEVICE_NUMBER
    }

    override fun initSdk(
        appKey: String?,
        mainBoardNum: String?,
        deviceType: String?,
        agreement: Int,
        agreementVer: String,
        vararg appInfoEntity: AppInfoEntity,
    ): IDeviceManager? {
        Constants.MAIN_BOARD_NUM = mainBoardNum
        setAgreementInfo(agreement, agreementVer, "00010001")
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["OSVer"] = DeviceUtils.getSDKVersionCode()
        map["MainBoardNum"] = mainBoardNum
        map["Memery"] = Runtime.getRuntime().maxMemory() / 1024L
        map["Disk"] = SDCardUtils.getInternalTotalSize() / 1048576L
        map["OSName"] = "Android"
        map["OSVerName"] = DeviceUtils.getSDKVersionName()
        map["RegCode"] = appKey
        map["DeviceType"] = deviceType
        val var8: Array<out AppInfoEntity> = appInfoEntity
        val var9 = appInfoEntity.size

        for (var10 in 0 until var9) {
            val infoEntity = var8[var10]
            infoEntity.hardVer = 9
        }

        map["AppInfo"] = JSONObject.toJSON(appInfoEntity)
        getUniversalMac(map)
        deviceConnectLoader.registerProduct(
            map,
            object : BaseResultObserver<BaseResult<RegisterEntity?>>() {
                override fun onSuccess(result: BaseResult<RegisterEntity?>) {
                    val data = result.data
                    LogUtils.d(*arrayOf<Any>("RegisterEntity response : " + JSON.toJSONString(result)))
                    if (data != null) {
                        Constants.SIGN_KEY = data.appKey
                        Constants.DEVICE_NUMBER = data.deviceName
                        initAliMq(data)
                        heartbeat(1L, 11)
                        checkUpdate(*appInfoEntity)
                    }
                }

                override fun onFailure(e: Throwable) {
                    if (initListener != null) {
                        if (e is ResponeThrowable) {
                            val throwablex = e as ResponeThrowable
                            initListener!!.registerFailed(
                                throwablex.code,
                                throwablex.message
                            )
                        } else if (e is ExceptionHandle.ServerException) {
                            val throwable = e as ExceptionHandle.ServerException
                            initListener!!.registerFailed(
                                throwable.code,
                                throwable.message
                            )
                        } else {
                            initListener!!.registerFailed(-9999L, e.message)
                        }
                    }
                }
            })
        return instance
    }

    override fun setAgreementInfo(agreement: Int, agreementVer: String, productFlag: String) {
        this.agreement = agreement
        this.agreementVer = agreementVer
        this.productFlag = productFlag
    }

    fun initSdkNew(
        appKey: String?,
        mainBoardNum: String?,
        deviceType: String?,
        agreement: Int,
        agreementVer: String,
        vararg appInfoEntity: AppInfoEntity
    ): YchDeviceManager {
        Constants.MAIN_BOARD_NUM = mainBoardNum
        setAgreementInfo(agreement, agreementVer, "00010001")
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["OSVer"] = DeviceUtils.getSDKVersionCode()
        map["MainBoardNum"] = mainBoardNum
        map["Memery"] = Runtime.getRuntime().maxMemory() / 1024L
        map["Disk"] = SDCardUtils.getInternalTotalSize() / 1048576L
        map["OSName"] = "Android"
        map["OSVerName"] = DeviceUtils.getSDKVersionName()
        map["RegCode"] = appKey
        map["DeviceType"] = deviceType
        val var8: Array<out AppInfoEntity> = appInfoEntity
        val var9 = appInfoEntity.size
        for (var10 in 0 until var9) {
            val infoEntity = var8[var10]
            infoEntity.hardVer = 9
        }
        map["AppInfo"] = JSONObject.toJSON(appInfoEntity)
        getUniversalMac(map)
        logFile("initsdk=${GsonUtil.getInstance()?.toJson(map)}")
        deviceConnectLoader.registerProduct(
            map,
            object : BaseResultObserver<BaseResult<RegisterEntity?>>() {
                override fun onSuccess(result: BaseResult<RegisterEntity?>) {
                    val data = result.data
                    LogUtils.d(*arrayOf<Any>("RegisterEntity response : " + JSON.toJSONString(result)))
                    if (data != null) {
                        Constants.SIGN_KEY = data.appKey
                        Constants.DEVICE_NUMBER = data.deviceName
                        initAliMq(data)
                        heartbeat(1L, 11)
                        checkUpdate(*appInfoEntity)
                    }
                }

                override fun onFailure(e: Throwable) {
                    if (initListener != null) {
                        if (e is ResponeThrowable) {
                            val throwablex = e as ResponeThrowable
                            initListener!!.registerFailed(
                                throwablex.code,
                                throwablex.message
                            )
                        } else if (e is ExceptionHandle.ServerException) {
                            val throwable = e as ExceptionHandle.ServerException
                            initListener!!.registerFailed(
                                throwable.code,
                                throwable.message
                            )
                        } else {
                            initListener!!.registerFailed(-9999L, e.message)
                        }
                    }
                }
            })
        return instance!!
    }

    private fun checkUpdate(vararg appInfoEntity: AppInfoEntity) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["Apps"] = JSONObject.toJSON(appInfoEntity)
        getUniversalMac(map)
        deviceConnectLoader.checkUpdate(
            map,
            object : BaseResultObserver<BaseResult<DeviceUpdateEntity>>() {
                override fun onSuccess(baseResult: BaseResult<DeviceUpdateEntity>) {
                    val data = baseResult.data as DeviceUpdateEntity
                    if (data != null && data.updates != null) {
                        if (data.updates.isEmpty()) {
                            getDeviceConfig()
                        } else {
                            if (initListener != null) {
                                val updateUrls: MutableList<String> = ArrayList<String>(3)
                                val var4: Iterator<*> =
                                    (baseResult.data as DeviceUpdateEntity).updates.iterator()
                                while (var4.hasNext()) {
                                    val update = var4.next() as UpdatesDTO
                                    updateUrls.add(update.downUrl)
                                }
                                val updateUrlArrays = arrayOfNulls<String>(updateUrls.size)
                                updateUrls.forEachIndexed { index, url ->
                                    updateUrlArrays[index] = url
                                }
                                initListener!!.needUpdate(*updateUrlArrays)
                            }
                            getDeviceConfig()
                        }
                    } else {
                        this.onFailure(Throwable("无法获取更新信息"))
                    }
                }

                override fun onFailure(e: Throwable) {
                    universalFailure("UPDATE", e)
                }
            })
    }

    override fun getDeviceConfig() {
        this.getDeviceConfig(Constants.hardwareDeviceId)
    }

    override fun getDeviceConfig(hardwareId: String?) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        if (hardwareId != null) {
            map["MachineMacID"] = hardwareId
        }
        getUniversalMac(map)
        deviceConnectLoader.getDeviceConfig(
            map,
            object : BaseResultObserver<BaseResult<RemoteDeviceConfigEntity>?>() {
                override fun onSuccess(entityBaseResult: BaseResult<RemoteDeviceConfigEntity>?) {
                    if (entityBaseResult == null) {
                        this.onFailure(Throwable("未能获取到配置信息"))
                    } else {
                        data = entityBaseResult.data as RemoteDeviceConfigEntity
                        if (data == null) {
                            this.onFailure(Throwable("未能获取到配置信息"))
                        } else {
                            getDeviceConfigCount++
                            if (data!!.getStepIndex() == 0) {
                                ThreadUtils.runOnUiThreadDelayed({
                                    if (getDeviceConfigCount >= 3) {
                                        LogUtilsX.e("DeviceConfig\n重试3次后失败")
                                        initListener!!.bindStatus(
                                            false,
                                            Constants.DEVICE_NUMBER
                                        )
                                    } else {
                                        getDeviceConfig(hardwareId)
                                    }
                                }, 2000L)
                            } else {
                                getDeviceConfigCount = 0
                                Constants.BASE_BUSINESS_URL =
                                    data!!.getLocalServer()
                                if (Constants.BASE_BUSINESS_URL == null || Constants.BASE_BUSINESS_URL.isEmpty()) {
                                    Constants.BASE_BUSINESS_URL =
                                        data!!.getBizServer()
                                }
                                if (Constants.BASE_BUSINESS_URL == null || Constants.BASE_BUSINESS_URL.isEmpty()) {
                                    LogUtilsX.e("DeviceConfig\nBASE_URL获取失败" + data.toString())
                                }
                                if (initListener != null) {
                                    if (Constants.BASE_BUSINESS_URL == null || Constants.BASE_BUSINESS_URL.isEmpty()) {
                                        LogUtilsX.e(
                                            """
                                        DeviceConfig
                                        getDeviceConfigCount=${getDeviceConfigCount}\nBASE_URL获取失败${data.toString()}
                                        """.trimIndent()
                                        )
                                    }
                                    initListener?.bindStatus(
                                        data!!.getStepIndex() != 0,
                                        Constants.DEVICE_NUMBER
                                    )
                                }
                            }
                        }
                    }
                }

                override fun onFailure(e: Throwable) {
                    universalFailure("BIND", e)
                }
            })
    }

    override fun getBaseBusinessUrl(): String? {
        return Constants.BASE_BUSINESS_URL
    }

    override fun getRemoteDeviceConfigData(): RemoteDeviceConfigEntity? {
        return data
    }

    fun mqResponse(mTransId: String) {
        this.mqResponse(mTransId, 0, "")
    }

    fun mqResponse(mTransID: String, result: Int, msg: String?) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["TimeStamp"] = TimeUtils.getNowMills() / 1000L
        map["Result"] = result
        map["Message"] = msg
        map["TransID"] = mTransID
        getUniversalMac(map)
        deviceConnectLoader.messageQueueResult(
            map,
            object : BaseResultObserver<BaseResult<Any?>?>() {
                override fun onSuccess(stringBaseResult: BaseResult<Any?>?) {
                    LogUtils.i(*arrayOf<Any>("回复 MQ ： mTransID  -> " + mTransID))
                }

                override fun onFailure(throwable: Throwable) {}
            })
    }

    private fun initAliMq(data: RegisterEntity) {
        aliMessageQueueUtils =
            AliMessageQueueUtils.getInstance().isDebug(isDebug).initLog(isOpenLog)
                .registerPushConnect().initMessageQuery(
                    data.productKey,
                    data.deviceName,
                    data.deviceKey,
                    object : ILinkKitConnectListener {
                        override fun onError(error: AError) {
                            LogUtils.e(*arrayOf<Any>("LinkKit onError : " + JSON.toJSON(error)))
                            FileUtils.writeFile("阿里MQ连接失败：" + JSON.toJSON(error))
                            mAliMqRetryCount++
                            if (initListener != null) {
                                initListener!!.registerFailed(
                                    error.code.toLong(),
                                    error.msg + ", 重试次数: " + mAliMqRetryCount
                                )
                            }
                            AliMessageQueueUtils.getInstance().disConnect()
                            ThreadUtils.runOnUiThreadDelayed(
                                { initAliMq(data) },
                                10000L
                            )
                        }

                        override fun onInitDone(datax: Any) {
                            logFile("onInitDone：${GsonUtil.getInstance()?.toJson(datax)}")
                            mAliMqRetryCount = 0
                            FileUtils.writeFile("阿里MQ连接成功 初始化")
                            aliMessageQueueUtils?.mqSubscription()
                        }
                    }).setDeviceConnectListener { isConnect: Boolean ->
                    if (isConnect) {
                        FileUtils.writeFile("阿里MQ连接成功")
                        Constant.MQONLINE = true
                    } else {
                        FileUtils.writeFile("阿里MQ断开连接")
                        Constant.MQONLINE = false
                        if (initListener != null) {
                            initListener!!.onError(
                                "CONNECT",
                                -9999L,
                                "MQTT 连接断开"
                            )
                        }
                    }
                }.setEventListener { aliMessageEntity: AliMessageEntity? ->
                    if (aliMessageEntity != null) {
                        if (eventListener != null && !Constants.isCrashToCoin) {
                            LogUtils.i(
                                *arrayOf<Any>(
                                    "收到 MQ command ->" + aliMessageEntity.command + " \nTransID ->" + aliMessageEntity.transID
                                )
                            )
                            val dataJson: String
                            when (aliMessageEntity.command) {
                                "Bind" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        this.mqResponse(
                                            aliMessageEntity.transID,
                                            cmdBufferStack[aliMessageEntity.transID]!!,
                                            ""
                                        )
                                        return@setEventListener
                                    }
                                    getDeviceConfigCount = 0
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    this.mqResponse(aliMessageEntity.transID)
                                    eventListener!!.deviceBinding()
                                }

                                "Unbind" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        this.mqResponse(
                                            aliMessageEntity.transID,
                                            cmdBufferStack[aliMessageEntity.transID]!!,
                                            ""
                                        )
                                        return@setEventListener
                                    }
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    this.mqResponse(aliMessageEntity.transID)
                                    eventListener!!.deviceUnBinding()
                                }

                                "Reboot" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        this.mqResponse(
                                            aliMessageEntity.transID,
                                            cmdBufferStack[aliMessageEntity.transID]!!,
                                            ""
                                        )
                                        return@setEventListener
                                    }
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    this.mqResponse(aliMessageEntity.transID)
                                    eventListener!!.deviceReBoot()
                                }

                                "ExtractCoin" -> {
                                    if (Constants.deviceIsMaintenance) {
                                        this.mqResponse(
                                            aliMessageEntity.transID,
                                            351,
                                            "兑币机停用"
                                        )
                                        return@setEventListener
                                    }
                                    extractCoin(aliMessageEntity)
                                }

                                "ChangeCashPackage" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        this.mqResponse(
                                            aliMessageEntity.transID,
                                            cmdBufferStack[aliMessageEntity.transID]!!,
                                            ""
                                        )
                                        return@setEventListener
                                    }
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    this.mqResponse(aliMessageEntity.transID)
                                    eventListener!!.changeCashPackage()
                                }

                                "SetSetting" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        return@setEventListener
                                    }
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    dataJson = JSON.toJSONString(aliMessageEntity.data)
                                    ThreadUtils.executeByIo<Int>(object : SimpleTask<Int?>() {
                                        @Throws(Throwable::class)
                                        override fun doInBackground(): Int {
                                            return eventListener!!.setDeviceSetting(
                                                dataJson
                                            )
                                        }

                                        override fun onSuccess(responseCode: Int?) {
                                            if (responseCode == null) {
                                                mqResponse(aliMessageEntity.transID)
                                            } else {
                                                mqResponse(
                                                    aliMessageEntity.transID,
                                                    responseCode,
                                                    ""
                                                )
                                            }
                                            cmdBufferStack.put(
                                                aliMessageEntity.transID,
                                                responseCode
                                            )
                                        }
                                    }, 10)
                                }

                                "GetSetting" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        return@setEventListener
                                    }
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    dataJson = JSON.toJSONString(aliMessageEntity.data)
                                    ThreadUtils.executeByIo<Map<Int, Any>>(
                                        object :
                                            SimpleTask<Map<Int, Any>?>() {
                                            @Throws(Throwable::class)
                                            override fun doInBackground(): Map<Int, Any> {
                                                return eventListener!!.getDeviceSetting(
                                                    dataJson
                                                )
                                            }

                                            override fun onSuccess(responseCode: Map<Int, Any>?) {
                                                if (responseCode == null) {
                                                    mqResponse(
                                                        aliMessageEntity.transID,
                                                        1,
                                                        "未获取到响应信息"
                                                    )
                                                } else {
                                                    mqResponse(
                                                        aliMessageEntity.transID,
                                                        0,
                                                        ""
                                                    )
                                                }
                                                cmdBufferStack.put(
                                                    aliMessageEntity.transID,
                                                    0
                                                )
                                            }
                                        },
                                        10
                                    )
                                }

                                "SyncDev" -> {
                                    if (cmdBufferStack.containsKey(aliMessageEntity.transID)) {
                                        LogUtils.e(
                                            *arrayOf<Any>(
                                                "指令已接受,正在处理中 ： " + aliMessageEntity.command
                                            )
                                        )
                                        return@setEventListener
                                    }
                                    dataJson = JSON.toJSONString(aliMessageEntity.data)
                                    LogUtils.e(
                                        *arrayOf<Any>(
                                            "===停用指令： " + dataJson
                                        )
                                    )
                                    cmdBufferStack[aliMessageEntity.transID] = 0
                                    this.mqResponse(aliMessageEntity.transID)
                                    var status = 1
                                    if (!TextUtils.isEmpty(dataJson)) {
                                        val json = JSON.parseObject(
                                            dataJson,
                                            DeviceStatusBean::class.java
                                        ) as DeviceStatusBean
                                        if (json != null) {
                                            status = json.state
                                        }
                                    }
                                    eventListener!!.deviceStatues(status)
                                    this.mqResponse(aliMessageEntity.transID)
                                }

                                else -> this.mqResponse(aliMessageEntity.transID)
                            }
                        } else {
                            this.mqResponse(
                                aliMessageEntity.transID,
                                301,
                                "设备繁忙"
                            )
                            Constants.isCrashToCoin = false
                        }
                    }
                }
    }

    override fun pushDeviceSetting(hardwareId: String?, dataList: List<MqDeviceSetRequestData?>?) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["Atts"] = dataList
        map["MacID"] = this.macId
        deviceConnectLoader.pushDeviceSet(map, object : BaseResultObserver<BaseResult<Any?>?>() {
            override fun onSuccess(objectBaseResult: BaseResult<Any?>?) {}
            override fun onFailure(e: Throwable) {}
        })
    }

    override fun disMqConnect() {
        if (aliMessageQueueUtils != null) {
            aliMessageQueueUtils!!.disSubscription()
            aliMessageQueueUtils!!.disConnect()
        }
    }

    override fun initSdk(
        appKey: String?,
        mainBoardNum: String?,
        deviceType: String?,
        agreement: Int,
        agreementVer: String,
        appInfoEntity: AppInfoEntity?,
        initListener: IDeviceManager.InitListener?,
    ): IDeviceManager? {
        return this.initSdk(
            appKey, mainBoardNum, deviceType, agreement, agreementVer,
            appInfoEntity!!
        )!!.setInitListener(initListener)
    }

    override fun setInitListener(initListener: IDeviceManager.InitListener?): IDeviceManager? {
        this.initListener = initListener
        return instance
    }

    override fun debugger(isOpen: Boolean, useTestUrl: Boolean): IDeviceManager? {
        isDebug = isOpen
        this.useTestUrl = useTestUrl
        deviceConnectLoader.setIsDebug(useTestUrl)
        return instance
    }

    override fun logger(isOpen: Boolean): IDeviceManager? {
        isOpenLog = isOpen
        return instance
    }

    override fun connectTest(iConnectTestResponse: IConnectTestResponse): IDeviceManager? {
        deviceConnectLoader.connectTest(object :
            BaseResultObserver<BaseResult<ConnectTestEntity>>() {
            override fun onSuccess(result: BaseResult<ConnectTestEntity>) {
                LogUtils.d(*arrayOf<Any>("ConnectTestEntity : $result"))
                iConnectTestResponse.callBack(true, null as String?)
                val data = result.data as ConnectTestEntity
                val timestamp = data.timestamp
                val timeStampStr =
                    TimeUtils.millis2String(timestamp * 1000L + Constants.STANDARD_TIME_SPAN)
                Constants.NOW_TIME_SPAN =
                    TimeUtils.getTimeSpanByNow(
                        timestamp * 1000L + Constants.STANDARD_TIME_SPAN,
                        TimeConstants.MSEC
                    )
                LogUtils.d(
                    *arrayOf<Any>(
                        String.format(
                            "timeStampStr : %s -> timeStamp : %s",
                            timeStampStr,
                            timestamp * 1000L + Constants.STANDARD_TIME_SPAN
                        )
                    )
                )
            }

            override fun onFailure(e: Throwable) {
                iConnectTestResponse.callBack(false, e.message)
                universalFailure("CONNECT", e)
            }
        })
        return instance
    }

    fun heartbeat(wait: Long, deviceType: Int) {
        ThreadUtils.executeBySingleWithDelay<Boolean>(object : SimpleTask<Boolean?>() {
            @Throws(Throwable::class)
            override fun doInBackground(): Boolean? {
                val wifiManager =
                    App.getAppContext().applicationContext.getSystemService("wifi") as WifiManager
                val connectionInfo = wifiManager.connectionInfo
                val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
                if (connectionInfo != null) {
                    map["SSID"] = connectionInfo.ssid
                    map["Signal"] = connectionInfo.rssi
                    map["Delay"] = connectionInfo.linkSpeed
                } else {
                    map["SSID"] = ""
                    map["Signal"] = 100
                    map["Delay"] = 30
                }
                map["Agreement"] = agreement
                map["AgreeVer"] = agreementVer
                map["DeviceType"] = deviceType
                map["ProductNumber"] = "0x" + productFlag
                getUniversalMac(map)
                deviceConnectLoader.deviceHeartbeat(
                    map,
                    object : BaseResultObserver<BaseResult<HeartbeatEntity?>?>() {
                        override fun onSuccess(stringBaseResult: BaseResult<HeartbeatEntity?>?) {
                            heartbeat(300L, deviceType)
                        }

                        override fun onFailure(e: Throwable) {
                            universalFailure("heartbeat", e)
                            heartbeat(300L, deviceType)
                        }
                    })
                return null
            }

            override fun onSuccess(result: Boolean?) {}
        }, wait, TimeUnit.SECONDS, 10)
    }

    override fun subDeviceRegister(
        machineID: String?,
        productCode: String,
        hardVer: Int,
        softVer: Int,
        appName: String?,
        appTitle: String?,
        observer: Observer<BaseResult<SubRegisterEntity?>?>?,
    ) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["MachineID"] = machineID
        map["ProductCode"] = "0x$productCode"
        map["HardVer"] = hardVer
        map["SoftVer"] = softVer
        map["AppName"] = appName
        map["AppTitle"] = appTitle
        map["Union"] = 1
        getUniversalMac(map)
        deviceConnectLoader.subDeviceRegister(map, observer)
    }

    override fun deviceErrorSubmit(errorType: Int, errorMsg: String?) {
        val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
        map["ErrorCode"] = errorType
        map["FaultDeviceType"] = 1
        map["Urgent"] = 2
        getUniversalMac(map)
        deviceConnectLoader.pushDeviceError(map, object : BaseResultObserver<BaseResult<Any?>?>() {
            override fun onSuccess(stringBaseResult: BaseResult<Any?>?) {}
            override fun onFailure(e: Throwable) {
                universalFailure("DEVICE_ERROR", e)
            }
        })
    }

    private fun getUniversalMac(map: MutableMap<String?, Any?>) {
        map["MacID"] = this.macId
        map["TimeSpan"] = TimeUtils.getNowMills()
    }

    override fun getMacId(): String? {
        return getMacId(Constants.MAIN_BOARD_NUM)
    }

    fun getMacId(macId: String): String? {
        val signatureTemp = SignatureUtils.getSignature(macId, "3A5B6BF5FAB891783A5B6CF4FAF79275")
        return macId + signatureTemp.substring(0, 4)
    }

    override fun setEventListener(eventListener: IMqMessageListener?): IDeviceManager? {
        this.eventListener = eventListener
        return instance
    }

    private fun universalFailure(errorType: String, e: Throwable) {
        if (initListener != null) {
            if (e is ResponeThrowable) {
                val throwable = e as ResponeThrowable
                initListener!!.onError(errorType, throwable.code, throwable.message)
            } else if (e is ExceptionHandle.ServerException) {
                val throwable = e as ExceptionHandle.ServerException
                initListener!!.onError(errorType, throwable.code, throwable.message)
            } else {
                initListener!!.onError(errorType, -9999L, e.message)
            }
        }
    }

    override fun getSdkVersion(): String? {
        return "1.0.0.9"
    }

    private fun extractCoin(aliMessageEntity: AliMessageEntity) {
        LogUtils.e(*arrayOf<Any>("----收到出币MQ"))
        val transTime = Constants.STANDARD_TIME_SPAN + aliMessageEntity.validityDate * 1000L
        LogUtils.d(*arrayOf<Any>("EXTRACT_COIN : " + TimeUtils.millis2String(transTime)))
        LogUtils.d(*arrayOf<Any>("EXTRACT_COIN : " + TimeUtils.millis2String(transTime - Constants.NOW_TIME_SPAN)))
        val timeSpanByNow =
            TimeUtils.getTimeSpanByNow(transTime - Constants.NOW_TIME_SPAN, TimeConstants.SEC)
        LogUtils.d(*arrayOf<Any>(String.format("EXTRACT_COIN : timeSpanByNow %s s", timeSpanByNow)))
        if (timeSpanByNow < -5L) {
            LogUtils.e(*arrayOf<Any>("----出币事件过期"))
            LogUtils.i(*arrayOf<Any>("EXTRACT_COIN : 过期事件"))
            if (eventListener != null) {
                eventListener!!.pushLog(
                    "MQ发出到设备 时间间隔 ：（S） " + timeSpanByNow + " \n出币事件过期: " + aliMessageEntity.toString()
                )
            }
        } else {
            val dataJson = JSON.toJSONString(aliMessageEntity.data)
            if (!mQCoinBufferStack.containsKey(aliMessageEntity.transID)) {
                mQCoinBufferStack[aliMessageEntity.transID] =
                    MqCoinEntity(getOrderId(dataJson), 1)
                LogUtils.e(
                    *arrayOf<Any>(
                        "----出币MQ添加到缓存中" + getOrderId(
                            dataJson
                        )
                    )
                )

                eventListener!!.extractCoin(dataJson)

//                ThreadUtils.executeByIo<Int>(object : SimpleTask<Int>() {
//                    @Throws(Throwable::class)
//                    override fun doInBackground(): Int {
//                        LogUtils.e(*arrayOf<Any>("----调用马达出币方法"))
//                        return eventListener!!.extractCoin(dataJson)
//                    }
//
//                    override fun onSuccess(responseCode: Int) {
//                        LogUtils.e(*arrayOf<Any>("----接收马达返回状态 = " + responseCode))
//                        val entity =
//                            mQCoinBufferStack.get(aliMessageEntity.transID) as MqCoinEntity
//                        if (entity != null) {
//                            entity.orderStatus = 3
//                            entity.deviceStatus = responseCode!!
//                            mQCoinBufferStack.put(
//                                aliMessageEntity.transID,
//                                entity
//                            )
//                        }
//                        mqExtractCoinResponse(
//                            aliMessageEntity.transID,
//                            responseCode,
//                            ""
//                        )
//                    }
//                }, 10)
            } else {
                LogUtils.e(*arrayOf<Any>("----出币事件存在缓存中"))
                LogUtils.e(*arrayOf<Any>("指令已接受,正在处理中 ： " + aliMessageEntity.command))
                val mqCoinEntity = mQCoinBufferStack[aliMessageEntity.transID]
                if (mqCoinEntity != null && TextUtils.equals(
                        mqCoinEntity.orderId,
                        getOrderId(dataJson)
                    )
                ) {
                    LogUtils.e(*arrayOf<Any>("----缓存中有该订单"))
                    if (mqCoinEntity.orderStatus == 2 || mqCoinEntity.orderStatus == 5) {
                        LogUtils.e(*arrayOf<Any>("----该订单状态为未回复或者回复失败"))
                        mqCoinEntity.orderStatus = 3
                        mQCoinBufferStack[aliMessageEntity.transID] = mqCoinEntity
                        mqExtractCoinResponse(
                            aliMessageEntity.transID,
                            mqCoinEntity.deviceStatus,
                            ""
                        )
                    }
                }
            }
        }
    }

    fun mqExtractCoinResponse(mTransID: String, result: Int, msg: String) {
        FileUtils.writeFile("回复MQ：mTransID = $mTransID result = $result msg = $msg")
        if (result == 303) {
            LogUtils.e(*arrayOf<Any>("----回复MQ result = " + result))
            LogUtilsX.e(
                "303不回复出币MQ",
                "时间：" + getCurrentDate("yyyy-MM-dd HH:mm:ss") + "mTransID = " + mTransID + " result = " + result + " msg = " + msg
            )
        } else {
            LogUtils.e(*arrayOf<Any>("----回复MQ"))
            val map: MutableMap<String?, Any?> = TreeMap<String?, Any?>()
            map["TimeStamp"] = TimeUtils.getNowMills() / 1000L
            map["Result"] = result
            map["Message"] = msg
            map["TransID"] = mTransID
            getUniversalMac(map)
            deviceConnectLoader.messageQueueResult(
                map,
                object : BaseResultObserver<BaseResult<Any?>?>() {
                    override fun onSuccess(stringBaseResult: BaseResult<Any?>?) {
                        LogUtils.e(*arrayOf<Any>("----MQ回复成功" + mTransID))
                        if (mQCoinBufferStack.containsKey(mTransID)) {
                            val entity =
                                mQCoinBufferStack.get(mTransID) as MqCoinEntity
                            entity.orderStatus = 4
                            mQCoinBufferStack.put(mTransID, entity)
                            eventListener?.updateOrder(
                                entity.orderId,
                                mTransID,
                                entity.deviceStatus,
                                "MQ回复成功"
                            )
                        }
                        mQResponseTimes = 0
                    }

                    override fun onFailure(throwable: Throwable) {
                        LogUtils.e(*arrayOf<Any>("----MQ回复失败 失败次数 = " + mQResponseTimes))
                        if (eventListener != null) {
                            eventListener!!.pushLog(
                                "----MQ回复失败 失败次数 = " + mQResponseTimes + "   失败事务ID = " + mTransID + " \n " + throwable.message
                            )
                        }
                        if (mQResponseTimes < 3) {
                            mQResponseTimes++
                            mqExtractCoinResponse(mTransID, result, msg)
                        } else {
                            if (mQCoinBufferStack.containsKey(mTransID)) {
                                val entity =
                                    mQCoinBufferStack.get(mTransID) as MqCoinEntity
                                entity.orderStatus = 5
                                mQCoinBufferStack.put(mTransID, entity)
                                eventListener?.updateOrder(
                                    entity.orderId,
                                    mTransID,
                                    entity.deviceStatus,
                                    "MQ回复失败"
                                )
                            }
                            mQResponseTimes = 0
                        }
                    }
                })
        }
    }

    private fun getOrderId(dataJson: String): String {
        var orderId = ""
        if (!TextUtils.isEmpty(dataJson)) {
            val data = JSON.parseObject(
                dataJson,
                AliDataEntity::class.java
            ) as AliDataEntity
            if (data != null) {
                orderId = data.orderID
            }
        }
        return orderId
    }

    private fun getCurrentDate(format: String): String {
        var format: String? = format
        if (TextUtils.isEmpty(format)) {
            format = "yyyy-MM-dd HH:mm:ss"
        }
        val simpleDateFormat = SimpleDateFormat(format)
        return simpleDateFormat.format(Date())
    }

    /**
     * 上报出币结果
     * @param responseCode 状态码 0-出币成功 1-出币失败
     * @param transId 事务id（订单id）
     */
    fun repExtractCoinResult(responseCode: Int, transId: String) {
        val entity =
            mQCoinBufferStack.get(transId) as MqCoinEntity
        if (entity != null) {
            entity.orderStatus = 3
            entity.deviceStatus = responseCode!!
            mQCoinBufferStack.put(
                transId,
                entity
            )
        }
        mqExtractCoinResponse(
            transId,
            responseCode,
            ""
        )
    }



}